home *** CD-ROM | disk | FTP | other *** search
- /* main.c
- This is a quickie program to generate a mandelbrot set on a Retina
- screen in 256 colors. */
-
- #include <stdlib.h>
- #include <stdio.h>
- #include <math.h>
-
- #ifdef _M68881
- #include <m68881.h>
- #endif
-
- #include <exec/libraries.h>
-
- #include <clib/exec_protos.h>
- #include <clib/intuition_protos.h>
- #include <devices/timer.h>
- #include <clib/alib_protos.h>
- #include <time.h>
-
- #include <pragmas/exec_pragmas.h>
- #include <pragmas/intuition_pragmas.h>
-
- #include "retina.h"
- #include "retina_protos.h"
- #include "retina_pragmas.h"
-
- #define MAX_ORBITS 256
-
- /* uncomment the following line to use my_RectFill */
-
- #define MYRECTFILL 1
-
- /* uncomment the following line to avoid repeating calculations */
- /* WARNING: For some reason this creates code that will cause
- stack overflow errors on any image larger than 320x400 or so */
- /*
- #define NOREPEATCALC
- */
-
- struct BrotPoint {
- unsigned int x, y;
- double r, i;
- #ifndef NOREPEATCALC
- int orbits; /* -2 if untested, -1 if never escapes,
- >= 0 otherwise */
- #endif
- };
-
- static int max_orbits = MAX_ORBITS;
-
- void Compute_Block(struct BrotPoint, struct BrotPoint);
- short int __inline __regargs Test_Point(double, double);
- #ifdef MYRECTFILL
- void __inline __regargs my_RectFill(unsigned int, unsigned int,
- unsigned int, unsigned int);
- #endif
-
- /* stack space must be BIG */
- long __stack = 100000;
-
- /* version string */
- UBYTE vers[] = "$VER: RetinaMand V0.1 (18.7.93)";
-
- extern struct IntuitionBase *IntuitionBase;
- struct _xy_RetinaBase *RetinaBase;
- struct DefaultScreenInfo screen_info;
-
- int __oslibversion = 37;
-
- double dr, di;
- struct RetinaScreen *rScreen;
-
- int main(int argc, char *argv[])
- {
- register int i, rstep, gstep, bstep;
- register UBYTE foo, bar, baz;
- struct BrotPoint start, end;
-
- if ((RetinaBase = (struct _xy_RetinaBase *)
- OpenLibrary("retina.library", 2L)) != NULL) {
- if ((IntuitionBase = (struct IntuitionBase *)
- OpenLibrary("intuition.library", 37L)) != NULL) {
- if ((rScreen = Retina_OpenScreen(RSCR_STDWIDTH, RSCR_STDHEIGHT,
- MID_DEFAULT_08,
- RSFF_AUTOADJUST, 0L))
- != NULL) {
- printf("Screen Opened successfully: %d by %d\n",
- rScreen->_rs_Width, rScreen->_rs_Height);
-
- /* set up screen colors; color 0 must always be black */
- Retina_SetPalette(rScreen, 0, 0, 0, 0);
- srand48((long) time(NULL));
- foo = (lrand48() >> 3) % 256;
- bar = (lrand48() >> 4) % 256;
- baz = (lrand48() >> 3) % 256;
- rstep = bstep = (lrand48() >> 5) % 16;
- gstep = (lrand48() >> 5) % 10;
- for (i = 1; i < 256; i++) {
- Retina_SetPalette(rScreen, i, foo, bar, baz);
- foo += rstep; foo %= 256;
- bar += gstep; bar %= 256;
- baz += bstep; baz %= 256;
- }
- Retina_SetDrMd(rScreen, RDM_JAM1);
-
- dr = (2.0 - (-2.0))/((double) rScreen->_rs_Width);
- di = (-1.5 - 1.5)/((double) rScreen->_rs_Height);
-
- /* OK, folks, enough initializing. Let's call the
- Mbrot routine. */
- start.x = 0; start.r = -2.0; start.y = 0; start.i = 1.5;
- end.x = rScreen->_rs_Width >> 1; end.r = 0.0;
- end.y = rScreen->_rs_Height >> 1; end.i = 0.0;
- #ifndef NOREPEATCALC
- start.orbits = -2;
- end.orbits = -2;
- #endif
- Compute_Block(start, end);
- start.y = end.y + 1; start.i = end.i + di;
- end.y = rScreen->_rs_Height - 1; end.i = -1.5;
- Compute_Block(start, end);
- start.x = end.x + 1; start.r = end.r + dr;
- end.x = rScreen->_rs_Width - 1; end.r = 2.0;
- Compute_Block(start, end);
- start.y = 0; start.i = 1.5;
- end.y = rScreen->_rs_Height >> 1; end.i = 0.0;
- Compute_Block(start, end);
-
- printf("Hit any key to quit.\n");
- getch();
-
- Retina_CloseScreen(rScreen);
- }
- else {
- fprintf(stderr, "Unable to open Retina screen.\n");
- }
- }
- else {
- fprintf(stderr, "Can't open intuition.library V37+\n");
- }
- }
- else {
- fprintf(stderr, "Can not open retina.library!\n");
- }
- }
-
- void Compute_Block(struct BrotPoint uleft, struct BrotPoint lright)
- {
- unsigned int i;
- double j;
- short int q, z;
-
- if (lright.x - uleft.x < 2 && lright.y - uleft.y < 2) {
- #ifdef NOREPEATCALC
- q = Test_Point(uleft.r, uleft.i);
- if (q > 0) Retina_SetPixel(rScreen, uleft.x, uleft.y, q);
- #else
- if (uleft.orbits == -2)
- uleft.orbits = Test_Point(uleft.r, uleft.i);
- if (uleft.orbits > 0) Retina_SetPixel(rScreen, uleft.x, uleft.y,
- uleft.orbits);
- #endif
- q = Test_Point(uleft.r, lright.i);
- if (q > 0) Retina_SetPixel(rScreen, uleft.x, lright.y, q);
- #ifdef NOREPEATCALC
- q = Test_Point(lright.r, lright.i);
- if (q > 0) Retina_SetPixel(rScreen, lright.x, lright.y, q);
- #else
- if (lright.orbits == -2)
- lright.orbits = Test_Point(lright.r, lright.i);
- if (lright.orbits > 0) Retina_SetPixel(rScreen,
- lright.x, lright.y,
- lright.orbits);
- #endif
- q = Test_Point(lright.r, uleft.i);
- if (q > 0) Retina_SetPixel(rScreen, lright.x, uleft.y, q);
- return;
- }
-
- /* draw a box -- if the borders are all the same, then fill it that
- color */
- q = Test_Point(uleft.r, uleft.i); uleft.orbits = q;
- if (q > 0)
- Retina_SetPixel(rScreen, uleft.x, uleft.y, q);
- z = Test_Point(lright.r, lright.i); lright.orbits = z;
- if (z > 0)
- Retina_SetPixel(rScreen, lright.x, lright.y, z);
- if (z != q) {
- goto recurse;
- }
-
- /* top & bottom */
- for (i = uleft.x, j = uleft.r; i <= lright.x; i++, j += dr) {
- z = Test_Point(j, uleft.i);
- if (z != q) {
- goto recurse;
- }
- else {
- if (z > 0)
- Retina_SetPixel(rScreen, i, uleft.y, z);
- }
- z = Test_Point(j, lright.i);
- if (z != q) {
- goto recurse;
- }
- else {
- if (z > 0)
- Retina_SetPixel(rScreen, i, lright.y, z);
- }
- }
- /* left and right */
- for (i = uleft.y, j = uleft.i; i <= lright.y; i++, j += di) {
- z = Test_Point(uleft.r, j);
- if (z != q) {
- goto recurse;
- }
- else {
- if (z > 0)
- Retina_SetPixel(rScreen, uleft.x, i, z);
- }
- z = Test_Point(lright.r, j);
- if (z != q) {
- goto recurse;
- }
- else {
- if (z > 0)
- Retina_SetPixel(rScreen, lright.x, i, z);
- }
- }
-
- /* if we passed through all that, we draw a filled rectangle */
- if (q > 0) {
- Retina_SetAPen(rScreen, q);
-
- #ifdef MYRECTFILL
- my_RectFill(uleft.x, uleft.y, lright.x, lright.y);
- #else
- /* fakin' it with line drawing */
- for (i = uleft.y; i <= lright.y; i++)
- Retina_Line(rScreen, uleft.x, i, lright.x, i);
- #endif
- }
- return;
-
- recurse:
- {
- struct BrotPoint top, bot, left, right, middle;
-
- top.x = bot.x = middle.x = (uleft.x + lright.x) >> 1;
- left.y = right.y = middle.y = (uleft.y + lright.y) >> 1;
- top.r = bot.r = middle.r = (uleft.r + lright.r)/2.0;
- left.i = right.i = middle.i = (uleft.i + lright.i)/2.0;
- top.y = uleft.y; top.i = uleft.i;
- bot.y = lright.y; bot.i = lright.i;
- left.x = uleft.x; left.r = uleft.r;
- right.x = lright.x; right.r = lright.r;
- #ifndef NOREPEATCALC
- middle.orbits = top.orbits = bot.orbits = left.orbits =
- right.orbits = -2;
- #endif
-
- Compute_Block(uleft, middle);
- #ifdef NOREPEATCALC
- left.y += 1; left.i += di;
- #endif
- Compute_Block(left, bot);
- #ifdef NOREPEATCALC
- middle.x += 1; middle.y += 1;
- middle.r += dr; middle.i += di;
- top.x += 1; top.r += dr;
- #endif
- Compute_Block(middle, lright);
- Compute_Block(top, right);
- }
- }
-
- #ifdef MYRECTFILL
- void __inline __regargs my_RectFill(unsigned int x1, unsigned int y1,
- unsigned int x2, unsigned int y2)
- {
- short int tx1, tx2, v;
-
- /* a little magic because Retina_RectFill() ignores the low-order
- 3 bits of the x-coords for 256-color screens */
- tx1 = (x1 >> 3) + 1; tx2 = (x2 >> 3) - 1;
- tx1 <<= 3; tx2 <<= 3;
-
- if (tx2 > tx1) {
- Retina_RectFill(rScreen, tx1, y1, tx2, y2);
- if (x2 - tx2 > 1) {
- for (v = tx2; v <= x2; v++)
- Retina_Line(rScreen, v, y1, v, y2);
- }
- if (tx1 - x1 > 1) {
- for (v = x1; v <= tx1; v++)
- Retina_Line(rScreen, v, y1, v, y2);
- }
- }
- else {
- /* fake it with line drawing */
- for (v = y1; v <= y2; v++) {
- Retina_Line(rScreen, x1, v, x2, v);
- }
- }
- }
- #endif
-
- /* Test_Point() tests points in the C plane to determine
- whether they orbit stably or escape to infinity.
- Returns the escape velocity or -1 if the point is
- in the M-set. */
-
- short int __inline __regargs Test_Point(double cx, double cy)
- {
- double x = 0.0, y = 0.0, tx;
- register short int i;
-
- /* z = z^2 + c */
- for (i = 0; i < max_orbits; i++) {
- tx = x*x - y*y + cx;
- y = 2.0 * x * y + cy;
- x = tx;
- if (x*x + y*y > 4.0) {
- return(i);
- }
- }
- return(-1);
- }
-